﻿namespace com.u3d.bases.loader
{
    using com.bases.utils;
    using com.u3d.bases.debug;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public class ResMgr
    {
        private VerMgr _verMgr = new VerMgr();
        public GameObject asset;
        private BinLoadMgr binLoadMgr;
        public static ResMgr instance = new ResMgr();
        private Dictionary<string, IList<LoadItem>> loadingList = new Dictionary<string, IList<LoadItem>>();
        private Dictionary<string, IList<LoadProgressBack>> progressList = new Dictionary<string, IList<LoadProgressBack>>();
        internal ResLoadMgr resLoadMgr;
        private Dictionary<int, int> typeConfigList = new Dictionary<int, int>();

        public ResMgr()
        {
            this.regTypeConfig(0x3e8, 0x514);
            this.regTypeConfig(0x7d0, 0x514);
            this.regTypeConfig(0x1388, 0x514);
            this.regTypeConfig(0xbb8, 0x578);
            this.regTypeConfig(0xfa0, 0x3e8);
            this.regTypeConfig(0x1770, 0x44c);
            this.regTypeConfig(0x1b58, 0x44c);
            this.regTypeConfig(0x1f40, 0x4b0);
        }

        public void addProgress(string url, LoadProgressBack callback)
        {
            if ((callback != null) && !StringUtils.isEmpty(url))
            {
                if (!this.progressList.ContainsKey(url))
                {
                    this.progressList.Add(url, new List<LoadProgressBack>());
                }
                this.progressList[url].Add(callback);
            }
        }

        public void initBinLoadMgr(BinLoadMgr binLoadMgr)
        {
            if (this.binLoadMgr == null)
            {
                this.binLoadMgr = binLoadMgr;
                this.binLoadMgr.loadback = new LoadFinishBack(this.loadCompleteHandler);
                this.binLoadMgr.errorback = new LoadFinishBack(this.loadErrorHandler);
                this.binLoadMgr.progressback = new LoadProgressBack(this.loadProgressHandler);
                this.resLoadMgr = new ResLoadMgr(binLoadMgr, this.versionMgr);
            }
        }

        public UnityEngine.Object load(string url, System.Type type = null)
        {
            Log.info(this, url);
            if (StringUtils.isEmpty(url))
            {
                return null;
            }
            if (ResPool.instance.hasLoadedRes(url))
            {
                return ResPool.instance.getLoaedRes(url);
            }
            string path = url;
            return ((type == null) ? Resources.Load(path) : Resources.Load(path, type));
        }

        public UnityEngine.Object[] loadAll(string url, System.Type type = null)
        {
            if (StringUtils.isEmpty(url))
            {
                return null;
            }
            string path = this.versionMgr.getLoadUrl(url);
            return ((type == null) ? Resources.LoadAll(path) : Resources.LoadAll(path, type));
        }

        public UnityEngine.Object[] loadAllAsset(string url, bool unload = true)
        {
            WWW www = this.LoadAssetBundle(PathURL + url);
            UnityEngine.Object[] objArray = null;
            objArray = www.assetBundle.LoadAll();
            if (unload)
            {
                www.assetBundle.Unload(false);
            }
            www.Dispose();
            www = null;
            return objArray;
        }

        public T loadAsset<T>(string url, string name = null, bool unload = true) where T: UnityEngine.Object
        {
            T mainAsset;
            Log.info(this, "start loading asset" + PathURL + url + " " + typeof(T).Name);
            WWW www = this.LoadAssetBundle(PathURL + url);
            if (name == null)
            {
                mainAsset = (T) www.assetBundle.mainAsset;
                Log.info(this, "loading mainAsset in " + PathURL + url + " " + typeof(T).Name + " " + mainAsset.name);
            }
            else
            {
                mainAsset = (T) www.assetBundle.Load(name, typeof(T));
                Log.info(this, "loading  in " + PathURL + url + " " + typeof(T).Name + " " + mainAsset.name);
            }
            if (unload)
            {
                www.assetBundle.Unload(false);
            }
            www.Dispose();
            www = null;
            return mainAsset;
        }

        private WWW LoadAssetBundle(string path)
        {
            return new WWW(path);
        }

        private void loadCompleteHandler(string url, object[] args = null)
        {
            if (this.loadingList.ContainsKey(url))
            {
                IList<LoadItem> list = this.loadingList[url];
                if (this.binLoadMgr.isTrace)
                {
                    Log.info(this, string.Concat(new object[] { "-loadCompleteHandler() url:", url, " 加载成功,即将回调:", (list == null) ? 0 : list.Count, " 个函数！" }));
                }
                this.removeProgress(url);
                this.loadingList.Remove(url);
                for (LoadItem item = null; list.Count > 0; item = null)
                {
                    item = list[0];
                    list.Remove(item);
                    item.call();
                    item.dispose();
                }
            }
        }

        private void loadErrorHandler(string url, object[] args = null)
        {
            if (this.loadingList.ContainsKey(url))
            {
                IList<LoadItem> list = this.loadingList[url];
                if (this.binLoadMgr.isTrace)
                {
                    Log.error(this, string.Concat(new object[] { "-loadErrorHandler() url:", url, " 加载失败！即将回调:", (list == null) ? 0 : list.Count, " 个函数！" }));
                }
                this.removeProgress(url);
                this.loadingList.Remove(url);
                for (LoadItem item = null; list.Count > 0; item = null)
                {
                    item = list[0];
                    list.Remove(item);
                    item.callError();
                    item.dispose();
                }
            }
        }

        private void loadProgressHandler(string url, int progress)
        {
            if (this.progressList.ContainsKey(url))
            {
                IEnumerator<LoadProgressBack> enumerator = this.progressList[url].GetEnumerator();
                try
                {
                    while (enumerator.MoveNext())
                    {
                        LoadProgressBack current = enumerator.Current;
                        current(url, progress);
                    }
                }
                finally
                {
                    if (enumerator == null)
                    {
                    }
                    enumerator.Dispose();
                }
            }
        }

        public bool loadRes(string url, int resType, LoadFinishBack callback = null, int priority = 0, LoadFinishBack errorback = null, object[] args = null)
        {
            if (StringUtils.isEmpty(url))
            {
                return false;
            }
            if (ResPool.instance.hasLoadedRes(url))
            {
                if (this.binLoadMgr.isTrace)
                {
                    Log.info(this, "-loadRes() url:" + url + " 缓存已有！");
                }
                if (callback != null)
                {
                    callback(url, args);
                }
                return true;
            }
            if (priority < 1)
            {
                priority = !this.typeConfigList.ContainsKey(resType) ? 500 : this.typeConfigList[resType];
            }
            LoadItem item = new LoadItem {
                url = url,
                args = args,
                resType = resType,
                priority = priority,
                callback = callback,
                errorback = errorback
            };
            if (this.loadingList.ContainsKey(url))
            {
                this.loadingList[url].Add(item);
            }
            else
            {
                this.loadingList.Add(url, new List<LoadItem>());
                this.loadingList[url].Add(item);
                this.binLoadMgr.addTask(item);
            }
            if (this.binLoadMgr.isTrace)
            {
                Log.info(this, "-loadRes() url:" + url + " 已放入加载队列！");
            }
            return true;
        }

        internal void loadScene(uint mapId, LoadItem item, LoadProgressBack progresFun = null)
        {
            this.binLoadMgr.loadScene(mapId, item, progresFun);
        }

        public void regTypeConfig(int resType, int priority)
        {
            if ((resType >= 1) && (priority >= 1))
            {
                this.removeTypeConfig(resType);
                this.typeConfigList.Add(resType, priority);
            }
        }

        private void removeProgress(string url)
        {
            if (!StringUtils.isEmpty(url) && this.progressList.ContainsKey(url))
            {
                this.progressList.Remove(url);
            }
        }

        public void removeProgress(string url, LoadProgressBack callback)
        {
            if ((callback != null) && !StringUtils.isEmpty(url))
            {
                IList<LoadProgressBack> list = !this.progressList.ContainsKey(url) ? null : this.progressList[url];
                if ((list != null) && (list.IndexOf(callback) != -1))
                {
                    list.Remove(callback);
                }
            }
        }

        public void removeTypeConfig(int resType)
        {
            if (this.typeConfigList.ContainsKey(resType))
            {
                this.typeConfigList.Remove(resType);
            }
        }

        public void setNumThread(int numThread)
        {
            if ((numThread >= 1) && (this.binLoadMgr != null))
            {
                this.binLoadMgr.maxNumThread = numThread;
            }
        }

        public void setNumTry(int numTry)
        {
            if ((numTry >= 1) && (this.binLoadMgr != null))
            {
                this.binLoadMgr.maxNumTry = numTry;
            }
        }

        public void setTrace(bool trace)
        {
            if (this.binLoadMgr != null)
            {
                this.binLoadMgr.isTrace = trace;
            }
        }

        public void unloadRes(string url, LoadFinishBack callback)
        {
            if (StringUtils.isEmpty(url))
            {
                return;
            }
            if (!this.loadingList.ContainsKey(url))
            {
                return;
            }
            IList<LoadItem> list = this.loadingList[url];
            IEnumerator<LoadItem> enumerator = list.GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    LoadItem current = enumerator.Current;
                    if (current.url.Equals(url) && (current.callback == callback))
                    {
                        this.binLoadMgr.unload(current);
                        list.Remove(current);
                        current.dispose();
                        goto Label_009A;
                    }
                }
            }
            finally
            {
                if (enumerator == null)
                {
                }
                enumerator.Dispose();
            }
        Label_009A:
            if (list.Count < 1)
            {
                this.removeProgress(url);
                this.loadingList.Remove(url);
            }
        }

        public int numThread
        {
            get
            {
                return ((this.binLoadMgr == null) ? 0 : this.binLoadMgr.maxNumThread);
            }
        }

        public int numTry
        {
            get
            {
                return ((this.binLoadMgr == null) ? 0 : this.binLoadMgr.maxNumTry);
            }
        }

        public static string PathURL
        {
            get
            {
                if (((Application.platform == RuntimePlatform.WindowsEditor) || (Application.platform == RuntimePlatform.WindowsPlayer)) || (Application.platform == RuntimePlatform.WindowsWebPlayer))
                {
                    return ("file:///" + Application.dataPath + "/StreamingAssets/");
                }
                if (Application.platform == RuntimePlatform.Android)
                {
                    return ("jar:file://" + Application.dataPath + "!/assets/");
                }
                if (Application.platform == RuntimePlatform.IPhonePlayer)
                {
                    return ("file:///" + Application.dataPath + "/Raw/");
                }
                return string.Empty;
            }
        }

        public VerMgr versionMgr
        {
            get
            {
                return this._verMgr;
            }
        }
    }
}

